﻿using System;
using System.IO;
using UtilZ.Dotnet.AudioPlayer.Base;
using UtilZ.Dotnet.AudioPlayer.Core;
using UtilZ.Dotnet.AudioPlayer.Native;
using UtilZ.Dotnet.Ex.Audio;

namespace UtilZ.Dotnet.AudioPlayer.Player
{
    /// <summary>
    /// 文件声音播放器
    /// </summary>
    public class FileSoundPlayer : SoundPlayerAbs
    {
        /// <summary>
        /// 当前播放的音频文件路径
        /// </summary>
        private string _fileName = null;

        /// <summary>
        /// 获取当前播放的音频文件路径
        /// </summary>
        public string FileName
        {
            get { return this._fileName; }
        }

        /// <summary>
        /// 获取或设置当前获取当前播放位置,单位/秒
        /// </summary>
        public double Position
        {
            get
            {
                if (base.HandleValid())
                {
                    long bytePos = BASSHelper.ChannelGetPosition(this._handle, BASSMode.BASS_POS_BYTE);
                    return BASSHelper.ChannelBytes2Seconds(this._handle, bytePos);
                }
                else
                {
                    return 0;
                }
            }
            set
            {
                if (base.HandleValid())
                {
                    long bytePos = BASSHelper.ChannelSeconds2Bytes(this._handle, value);
                    BASSHelper.ChannelSetPosition(this._handle, bytePos, BASSMode.BASS_POS_BYTE);
                }
                else
                {
                    throw new AudioException("未加载音频数据");
                }
            }
        }

        /// <summary>
        /// 播放时间,单位/秒
        /// </summary>
        public double Duration
        {
            get
            {
                if (base.HandleValid())
                {
                    long bytePos = BASSHelper.ChannelGetLength(this._handle, BASSMode.BASS_POS_BYTE);
                    return BASSHelper.ChannelBytes2Seconds(this._handle, bytePos);
                }
                else
                {
                    return 0;
                }
            }
        }


        private WaveInfo _waveInfo = null;
        /// <summary>
        /// 获取wave音频信息
        /// </summary>
        /// <returns></returns>
        protected override WaveInfo GetWaveInfo()
        {
            if (this._waveInfo == null && this.HandleValid())
            {
                BASS_CHANNELINFO_INTERNAL info = BASSHelper.ChannelGetInfo(this._handle);
                this._waveInfo = new WaveInfo(WaveEncoding.Pcm, info.freq, (short)info.chans, (short)info.origres)
                {
                    FilePath = this._fileName
                };
            }

            return this._waveInfo;
        }

        /// <summary>
        /// 播放完成事件
        /// </summary>
        public event EventHandler<PlayEndArgs> PlayEnd;

        private int _playEndSyncHandle;
        private readonly SYNCPROC _playEndNotifyCallback;
        //private readonly SYNCPROC _playPositionChangedNotifyCallback;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="id">播放器标识</param>
        public FileSoundPlayer(int id)
            : base(SoundPlayerType.File, id)
        {
            this._playEndNotifyCallback = new SYNCPROC(this.PlayEndNotify);
            //this._playPositionChangedNotifyCallback = new SYNCPROC(this.PlayPositionChangedNotify);
        }

        //private void PlayPositionChangedNotify(int handle, int channel, int data, IntPtr user)
        //{
        //    WavLoger.OnRaiseLog(this, "PlayPositionChangedNotify");
        //}

        private void PlayEndNotify(int handle, int channel, int data, IntPtr user)
        {
            this._waveInfo = null;

            var handler = this.PlayEnd;
            if (handler != null)
            {
                handler(this, new PlayEndArgs(this._fileName));
            }
        }

        /// <summary>
        /// 播放状态改变通知
        /// </summary>
        protected override void OnPlayStatusChanged()
        {
            base.OnPlayStatusChanged();

            var state = BASSHelper.ChannelIsActive(base._handle);
            if (state != BASSActive.BASS_ACTIVE_PAUSED &&
                state != BASSActive.BASS_ACTIVE_PAUSED_DEVICE &&
                state != BASSActive.BASS_ACTIVE_PLAYING)
            {
                this._waveInfo = null;
            }
        }

        /// <summary>
        /// 加载音频文件
        /// </summary>
        /// <param name="filePath">音频路径</param>
        public void LoadFile(string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                throw new ArgumentNullException(nameof(filePath), "文件路径不能为空或null");
            }

            if (!File.Exists(filePath))
            {
                throw new FileNotFoundException("音频文件不存在", filePath);
            }

            this._fileName = filePath;
            this.FreeBASS();
            base._handle = BASSHelper.StreamCreateFile(filePath);
            this._playEndSyncHandle = BASSHelper.ChannelSetSync(this._handle, BASSSync.BASS_SYNC_END, -1, this._playEndNotifyCallback, IntPtr.Zero);

            base.UpdateVolume();
            base.UpdatePlaySpeed();
            base.UpdateBalance();
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        protected override void FreeBASS()
        {
            this._waveInfo = null;
            base.FreeBASS();
            if (base.HandleValid())
            {
                BASSHelper.BASS_ChannelRemoveSync(base._handle, this._playEndSyncHandle);
            }
        }

    }

    /// <summary>
    /// 播放完成事件
    /// </summary>
    public class PlayEndArgs : EventArgs
    {
        /// <summary>
        /// 文件名
        /// </summary>
        public string FileName { get; private set; }

        /// <summary>
        /// 文件名
        /// </summary>
        /// <param name="fileName"></param>
        public PlayEndArgs(string fileName)
        {
            this.FileName = fileName;
        }
    }
}
